using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using static WaterCylinder.Object;
using static WaterCylinder.Math;
/*
地图生成器
*/

public class MapController : MonoBehaviour
{
    
    private static MapController _instance;
    public static MapController instance{
        get{
            if(_instance == null){
                _instance = FindAnyObjectByType<MapController>();
                if(_instance == null){
                    GameObject obj = new GameObject("MapController");
                    _instance = obj.AddComponent<MapController>();
                }
            }
            return _instance;
        }
    }
    
    public int seed;//种子码
    public LevelInfo _level;
    private LevelInfo insLevel;
    public LevelInfo level{
        get{
            if(insLevel == null){
                if(_level == null){
                    Debug.Log("Map未绑定level信息");
                    return null;
                }else{
                    insLevel = Instantiate(_level);
                }
            }
            return insLevel;
        }
    }
    
    /// <summary>
    /// 获取所有房间列表
    /// </summary>
    /// <returns></returns>
    public List<Room> rooms;

    public Room CreatRoom(Room room){
        Room res = Creat(room);
        res.transform.parent = transform;
        return res;
    }
    Dictionary<RoomType, int> RoomGenerationWeight;
    //设置RGW的值
    void SetW(int index = 0, int page = 0, int res = 0, int end = 0, int boss = 0){
        if(RoomGenerationWeight == null)foreach(RoomType t in Enum.GetValues(typeof(RoomType))){
            RoomGenerationWeight = new Dictionary<RoomType, int>{{t, 0}};
        }
        foreach(RoomType t in Enum.GetValues(typeof(RoomType))){
            int value = 0;
            switch(t){
                case RoomType.Index:value = index;break;
                case RoomType.Page:value = page;break;
                case RoomType.Res:value = res;break;
                case RoomType.End:value = end;break;
                case RoomType.BOSS:value = boss;break;
            }
            RoomGenerationWeight[t] = value;
        }
    }
    //终点房间是固定数量的房间，数量在LevelInfo里设置，连接到终点房间相当于随机连接到一个终点房间
    List<Room> endRooms;
    Room GetEndRoom(){
        if(endRooms == null){
            endRooms = new List<Room>();
            for(int i = 0; i<level.FindRoomInfoByType(RoomType.End).num; i++){
                endRooms.Add(CreatRoom(level.GetRoom(RoomType.End)));
            }
        }
        return endRooms[SeedRandom(0,endRooms.Count)];
    }
    //根据权重获取随机类型的随机房间
    Room GetRandomRoom(){
        int W = 0;
        foreach(var item in RoomGenerationWeight)
            W += item.Value;
        int rW = SeedRandom(1,W);
        int cW = 0;
        foreach(var item in RoomGenerationWeight){
            cW +=item.Value;
            if(rW <= cW){
                if(item.Key == RoomType.End){
                    return GetEndRoom();
                }else{
                    return CreatRoom(level.GetRoom(item.Key));
                }
            }
        }
        return null;
    }
    /// <summary>
    /// 创建地图
    /// </summary>
    public void CreatMap(){
        //创建初始房间
        rooms = new List<Room>(){CreatRoom(level.GetRoom(RoomType.Index))};
        List<Room> targets = new List<Room>{rooms[0]};
        List<Room> temp = new List<Room>();
        int pageN = level.FindRoomInfoByType(RoomType.Page).num;
        int pageCN = 0;
        int resN = level.FindRoomInfoByType(RoomType.Res).num;
        int resCN = 0;
        bool boss = false;
        //生成基准房间
        for(int i = 0; i<targets.Count; i++){
            Room target = targets[i];
            SetW();
            for(int j = 0; j<target.linkNum; j++){
                //根据不同类型的房间设置连接的房间的类型的权重
                switch (target.type){
                    case RoomType.Index:SetW(page:10);break;            //初始房间一定会连接到普通房间
                    case RoomType.Page:                                 //普通房间
                    if(resCN < resN)
                        SetW(page:50,res:50,end:(j+1)*20);              //当前资源房间数量没有达到上限
                    else                                                
                        SetW(page:10,end:(j+1)*50);                     
                    if(j == 0){
                        if(pageCN < pageN){
                            SetW(page:10);
                        }else if(resCN < resN){
                            SetW(res:10);
                        }else if(!boss){
                            SetW(boss:50*(pageCN-pageN),page:10);
                        }
                    }
                    if(boss)SetW(end:10);
                    break;
                    case RoomType.Res:
                    if(pageCN < pageN){
                        SetW(page:10);
                    }else{
                        if(resCN < resN)
                            SetW(page:50,res:5,end:50);
                        else
                            SetW(page:10,end:50);
                    }
                    break;
                }
                //根据权重生成房间
                Room r = GetRandomRoom();
                //Debug.Log($"Target: {target}\n Room: {r}\n DIC: "+DicToString(RoomGenerationWeight));
                if(r != null){
                    if(!rooms.Contains(r))rooms.Add(r);
                    if(!temp.Contains(r))temp.Add(r);
                    target.linkRooms.Add(r);
                    r.linkReturn = target;
                    if(r.type == RoomType.Page)pageCN++;
                    else if(r.type == RoomType.Res)resCN++;
                    else if(r.type == RoomType.BOSS)boss = true;
                }
            }
            //遍历到最后一个房间时切换到下一个层级
            if(i == targets.Count-1){
                targets.Clear();
                targets.AddRange(temp);
                i = -1;
                temp.Clear();
            }
        }
        //生成导航房间
        rooms.Add(CreatRoom(level.GetRoom(RoomType.Nav)));
        //给房间赋值ID
        for(int i = 0; i<rooms.Count; i++)rooms[i].roomId = i;

    }
    /// <summary>
    /// 根据种子获取随机数，包含左右边界
    /// </summary>
    /// <param name="l"></param>
    /// <param name="r"></param>
    /// <returns></returns>
    public float SeedRandom(float l, float r){
        return UnityEngine.Random.Range(l,r);
    }
    /// <summary>
    /// 根据种子获取随机数，仅包含左边界
    /// </summary>
    /// <param name="l"></param>
    /// <param name="r"></param>
    /// <returns></returns>
    public int SeedRandom(int l, int r){
        return UnityEngine.Random.Range(l,r);
    }
    public int SetSeed(int seed = 0){
        this.seed = seed==0?(int)Range(0,0x7FFFFFFF):seed;
        UnityEngine.Random.InitState(this.seed);
        return this.seed;
    }

    private void Awake() {
        if(seed == 0)SetSeed();
        if(level == null){
            Debug.Log("地图控制器没有设置level信息");
        }
    }

}
